package cn.xyfmzmy.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

// nio server 多路复用
public class NioServer {

    public static void main(String[] args) throws IOException {
        // selector相当于一个监听器，监听哪个channel可用
        Selector selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.bind(new InetSocketAddress("localhost",8080));
        // 注册，让selector监听ssc的accept事件
        ssc.register(selector, SelectionKey.OP_ACCEPT);
        while(true){
            selector.select();      //阻塞方法
            // 每个SelectionKey对应一个监听事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey key = iterator.next();
                iterator.remove();
                if(key.isAcceptable()){
                    // 若为accept事件，则对应的channel为ServerSocketChannel (这里拿到的就是上面的ssc)
                    // ServerSocketChannel本身不具备读写能力，真正读写的是SocketChannel
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
                    SocketChannel client = serverSocketChannel.accept();
                    client.configureBlocking(false);
                    //注册，让selector监听client的read事件
                    client.register(selector,SelectionKey.OP_READ);
                    System.out.println(client.getRemoteAddress() + "链接了");
                }
                if(key.isReadable()){
                    // 若为read事件，则对应的channel为SocketChannel
                    SocketChannel channel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    int length = channel.read(byteBuffer);
                    if(length == -1){
                        System.out.println(channel.getRemoteAddress() + "断开链接");
                        channel.close();
                    }else{
                        byteBuffer.flip();
                        byte[] buffer = new byte[byteBuffer.remaining()];
                        byteBuffer.get(buffer);
                        String message = new String(buffer);
                        System.out.println(message);
                    }

                }
            }
        }



    }
}
